package org.ycx.upms.client.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.ycx.upms.client.ISecurityMetaData;
import org.ycx.upms.common.constants.SecurityConstants;
import org.ycx.upms.dao.mapper.ISecPermissionMapper;
import org.ycx.upms.dao.mapper.ISecRolePermissionMapper;
import org.ycx.upms.dao.model.SecPermission;
import org.ycx.upms.dao.model.SecPermissionExample;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * Redis权限查询实现
 * Created by 杨 on 2017-06-27.
 */
public class RedisSecurityMetaDataImpl implements ISecurityMetaData {

    @Autowired
    private ISecRolePermissionMapper rolePermissionMapper;

    @Autowired
    private ISecPermissionMapper permissionMapper;

    @Autowired
    private StringRedisTemplate template;

    @Override
    public List<String> getGrantAuthority(HttpServletRequest request) {

        List<String> grants = new ArrayList<String> ();
        String flag = template.opsForValue ().get (SecurityConstants.SECURITY_LOAD_FLAG);
        if (!"1".equals (flag)) {
            loadGrants ();
        }
        Set<String> urls = template.opsForSet ().members (SecurityConstants.SECURITY_URLS);
        AntPathRequestMatcher antPathRequestMatcher = null;
        AntPathRequestMatcher antPathRequestMatcher2 = null;
        for (String url : urls) {
            if (url.startsWith ("/")) {
                antPathRequestMatcher = new AntPathRequestMatcher (url);
                if (antPathRequestMatcher.matches (request)) {
                    grants.addAll (template.opsForSet ().members ("sec_" + url));
                }
            } else {
                antPathRequestMatcher = new AntPathRequestMatcher (url);
                antPathRequestMatcher2 = new AntPathRequestMatcher ("/" + url);
                if (antPathRequestMatcher2.matches (request) || antPathRequestMatcher.matches (request)) {
                    grants.addAll (template.opsForSet ().members ("sec_" + url));
                }
            }

        }
        if (grants.size () > 0) {
            return grants;
        } else {
            return null;
        }
    }

    private void loadGrants() {
        //查询所有权限
        SecPermissionExample spe = new SecPermissionExample ();
        List<SecPermission> allPermissions = this.permissionMapper.selectByExample (spe);
        Map<String, Integer> urisAndPid = new HashMap<String, Integer> ();
        for (SecPermission sp : allPermissions) {
            template.opsForSet ().add (SecurityConstants.SECURITY_URLS, sp.getUri ());
            if (sp.getState ().equals ("1")) {//公共权限
                urisAndPid.put (sp.getUri (), 0);
            } else {
                urisAndPid.put (sp.getUri (), sp.getPermissionId ());
            }

            if (sp.getOther () != null && sp.getOther ().length () > 3) {
                String[] subURI = sp.getOther ().split (",");
                for (int i = 0; i < subURI.length; i++) {
                    if (!urisAndPid.containsKey (subURI)) {
                        template.opsForSet ().add (SecurityConstants.SECURITY_URLS, subURI[i]);
                        if (sp.getState ().equals ("1")) {//公共权限
                            urisAndPid.put (sp.getUri (), 0);
                        }
                        urisAndPid.put (subURI[i], sp.getPermissionId ());
                    }
                }
            }
        }
        //放置URI匹配表
        for (Map.Entry<String, Integer> map : urisAndPid.entrySet ()) {
            if (map.getValue ().equals (0)) {
                List<Integer> roles = this.rolePermissionMapper.selectAllRoles ();
                for (Integer role : roles) {
                    template.opsForSet ().add ("sec_" + map.getKey (), role + "");
                }
            } else {
                List<String> roles = this.rolePermissionMapper.selectByPermissionId (map.getValue ());
                if(roles!=null && roles.size () >0){
                    for (String role : roles) {
                        template.opsForSet ().add ("sec_" + map.getKey (), role);
                    }
                }else{
                    template.opsForSet ().add ("sec_" + map.getKey (), "denyAll");
                }
            }

        }
        template.opsForValue ().set (SecurityConstants.SECURITY_LOAD_FLAG, "1");
    }
}
